package com.learn.spring.event;

import com.learn.spring.event.config.AsyncConfiguration;
import com.learn.spring.event.order.PlaceOrderReqVO;
import com.learn.spring.event.service.AsyncService;
import com.learn.spring.event.service.OrderService;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;

@SpringBootTest
class SpringLearnEventAnnotionApplicationTests {

    @Test
    void contextLoads() {
    }
    @Autowired
    private OrderService orderService;

    @Autowired
    private AsyncService asyncService;

    @Autowired
    private ThreadPoolTaskExecutor getAsyncExecutor;

    @Test
    void placeOrder() {
        PlaceOrderReqVO placeOrderReqVO = new PlaceOrderReqVO();
        orderService.placeOrder(placeOrderReqVO);
    }

    /**
     *  模拟异常测试
     */
    @Test
    public void testAsyncExecutor() {
        // 调用异步方法
        asyncService.asyncMethodWithException();

        // 等待一段时间，确保异步方法有机会执行
        try {
            TimeUnit.SECONDS.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 验证线程池是否按配置工作
        assertTrue(getAsyncExecutor.getActiveCount() >= 0);
        assertTrue(getAsyncExecutor.getCorePoolSize() == 5);
        assertTrue(getAsyncExecutor.getMaxPoolSize() == 10);
    }

    /**
     *  测试异步方法异常处理
     */
    @Test
    public void testAsyncExceptionHandler() {
        AsyncConfiguration config = new AsyncConfiguration();
        ThreadPoolTaskExecutor executor = config.executor();

        // 调用异步方法，该方法会抛出异常
        asyncService.asyncMethodWithException();

        // 等待一段时间，确保异常处理器有机会处理异常
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 大量提交任务，触发拒绝策略
        for (int i = 0; i < 1000; i++) {
            final int taskId = i;
            executor.execute(() -> {
                try {
                    System.out.println("Task " + taskId + " is running...");
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            });
        }

    }

    /**
     * 通过executor.submit提交一个会抛出异常的任务，然后使用Future.get()方法获取任务结果，
     * 由于任务会抛出异常，Future.get()方法会抛出ExecutionException，我们可以捕获这个异常并进行断言。
     */
    @Test
    public void testThreadPoolException() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AsyncConfiguration.class);
        ThreadPoolTaskExecutor executor = context.getBean("fighter3AsyncExecutor", ThreadPoolTaskExecutor.class);

        Future<?> future = executor.submit(() -> {
            throw new RuntimeException("Simulated exception in task");
        });

        try {
            future.get();
            fail("Expected ExecutionException to be thrown");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (ExecutionException e) {
            assertTrue(e.getCause() instanceof RuntimeException);
        } finally {
            executor.shutdown();
            context.close();
        }
    }

}
